package com.zmn.oms.third.yunding;

import com.google.common.collect.Maps;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 云丁鹿客渠道对接的工具类
 *
 * @author xiewenbing
 * @date 2020/09/10
 */
@Slf4j
public class YundingUtil {

    public static double X_PI = 3.14159265358979324 * 3000.0 / 180.0;

    /**
     * 验证签名
     * @return
     */
    public static boolean verifySign(Map<String,String> params,String sign) {

        String signParam = makeSign(params);
        return StringUtils.isEmpty(signParam) ? true : (signParam.compareToIgnoreCase(sign) == 0 ? true : false);
    }

    /**
     * 生成签名
     * @return
     */
    public static String makeSign(Map<String,String> params) {
        if (Objects.isNull(params) || params.isEmpty()) {
            return null;
        }

        StringBuilder paramBuilder = new StringBuilder();
        paramBuilder.append(YundingConsts.APP_SECRET);
        for (String key : params.keySet()) {
            paramBuilder.append(key).append(params.get(key));
        }
        paramBuilder.append(YundingConsts.APP_SECRET);

        String sign = DigestUtils.md5Hex(paramBuilder.toString());

        log.info("【{}】 生成签名，【{}】【{}】【{}】",YundingConsts.CHANNEL_NAME,params.toString(),paramBuilder.toString(),sign);
        return sign;
    }

    /**
     * 将对象实体转换为map，按照名称排序
     * @param obj
     * @return
     * @throws IllegalAccessException
     */
    public static Map<String, String> objectToMap (Object obj){

        // 参数判断
        if (Objects.isNull(obj)) {
            return null;
        }

        Class<?> objClass = obj.getClass();
        TreeMap<String,String> map = Maps.newTreeMap();

        // 循环获取类和父类的字段，并取值
        while (objClass!=null && !("java.lang.object").equals(objClass.getName().toLowerCase())) {

            Field[] fields = objClass.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                String name = field.getName();
                Object value = null;
                try {
                    value = field.get(obj);
                } catch (IllegalAccessException exception) {
                   log.info("#YundingUtil#objectToMap# catch IllegalAccessException");
                }

                if (Objects.nonNull(value)) {
                    map.put(name, value.toString());
                }
            }

            objClass = objClass.getSuperclass();
        }

        return map;
    }

    /**
     * 发送 带参数的https请求
     * @param url
     * @param content
     * @return
     * @throws OmsBaseException
     */
    public static String postHttpsRequest(String url, String content) {

        if (StringUtils.isBlank(url)) {
            log.info("【{}】发送请求失败，URL参数不能为空",YundingConsts.CHANNEL_NAME);
            return null;
        }

        log.info("【{}】发送请求，URL【{}】,参数【{}】",YundingConsts.CHANNEL_NAME,url,content);
        String response = "";
        for (int i=0; i<3; i++) {
            try {

                if (url.matches("https(.*)")) {
                    response = HttpUtil.httpsPost(url, content);
                } else {
                    response = HttpUtil.httpPost(url, content);
                }

                if (StringUtil.isNotBlank(response)) {
                    break;
                }
            } catch (Exception exception) {
                log.info("【{}】发送请求失败,{}",YundingConsts.CHANNEL_NAME,Objects.nonNull(exception)? exception.getMessage():"网络请求异常");
            }
        }

        log.info("【{}】发送请求应答【{}】",YundingConsts.CHANNEL_NAME,response);
        return response;
    }

    /**
     * 高德 =》 百度
     * @param lat
     * @param lon
     * @return
     */
    public static double[] gaodeToBaidu(double lat, double lon) {
        double x = lon, y = lat;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * X_PI);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * X_PI);
        double tempLon = z * Math.cos(theta) + 0.0065;
        double tempLat = z * Math.sin(theta) + 0.006;

        String txtLng = String.format("%.6f",tempLon);
        String txtLat = String.format("%.6f",tempLat);

        double[] gps = {Double.valueOf(txtLat).doubleValue(),Double.valueOf(txtLng).doubleValue()};
        return gps;
    }

    public static void main(String[] args) {

    }
}
